package com.examsys.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.ibatis.session.SqlSession;

import com.examsys.util.DBUtil;

//数据访问层基类,T表示表对象的po实体类型，K表示表中的主键对应的类型
public abstract class AbstractBaseDao<T,K> implements IBaseDao<T,K> {

	/**
	 * 本方法用于更新，插入，删除等
	 * @param sql 带参的数据库语句
	 * @param params 参数列表
	 * @return
	 * @throws Exception
	 * sql="Insert into ADMIN (ID,ROLE_ID,USER_NAME,USER_PASS,PHONE,LOGIN_TIMES,CREATE_DATE,LOGIN_DATE,STATUS,REMARK) values (?,?,?,?,?,?,?,?,?,?);"
	 */
	protected int execute(String sql, Object[] params)
          throws Exception {
		SqlSession conn = null;//数据库连接对象
      PreparedStatement ps = null;//数据库语句发送对象
      int result = 0;
      /*try {
          conn = DBUtil.getSession();//建立数据库连接
          ps = conn.prepareStatement(sql);//发送数据库语句
          if (params != null) {//如果有参数，则设置参数进语句发送对象中
              for (int i = 0; i < params.length; i++) {
                  ps.setObject(i + 1, params[i]);
              }
          }
          result = ps.executeUpdate();//执行更新或插入动作
      } catch (Exception e) {
          e.printStackTrace();
          throw new Exception("Error at:" + getClass().getName() + "execute()");
      } finally {
          DBUtil.close(ps);//关闭资源
      }*/
      return result;
  }

	/**
	 * 本方法用于批量更新，插入，删除等
	 * @param sql 带参的数据库语句
	 * @param list 参数列表
	 * @return
	 * @throws Exception
	 * sql="Insert into ADMIN (ID,ROLE_ID,USER_NAME,USER_PASS,PHONE,LOGIN_TIMES,CREATE_DATE,LOGIN_DATE,STATUS,REMARK) values (?,?,?,?,?,?,?,?,?,?);"
	 */
  protected int batchExcute(String sql, List<Object[]> list)
          throws Exception {
      if (list == null) {//如果没有参数，则返回，不执行后续代码
          return 0;
      }
      Connection conn = null;//数据库连接对象
      PreparedStatement ps = null;//数据库语句发送对象
      /*try {
          conn = DBUtil.getConnection();//建立数据库连接
          ps = conn.prepareStatement(sql);//发送数据库语句
          for (Object[] obj : list) {//如果有参数，则设置参数进语句发送对象中
              for (int i = 0; i < obj.length; i++) {
                  ps.setObject(i + 1, obj[i]);
              }
              ps.addBatch();//准备批量动作
          }
          int[] ii = ps.executeBatch();//执行更新或插入动作
          return ii.length;//返回执行成功的条数
      } catch (Exception e) {
          e.printStackTrace();
          throw new Exception("Error at:" + getClass().getName() + "batchExcute()");
      } finally {
          DBUtil.close(ps);//关闭资源
      }*/
      return 0;
  }

  /**
   * 本方法用于执行查询，结果集中不允许重复，则只有一条记录
   * @param sql 带参的数据库语句
   * @param params 参数列表
   * @return
   * @throws Exception
   * sql="SELECT * FROM ADMIN where id=?"
   */
  protected Map uniqueQuery(String sql, Object[] params)
          throws Exception {
      Map m = null;
      List list = query(sql, params);
      if ((list != null) && (list.size() > 0)) {
          m = (Map) list.get(0);//这里这个零表示下标，只拿一条且是第一条的数据
      }
      return m;
  }

  /**
   * 本方法用于执行查询，结果集中允许重复，则多条记录
   * @param sql 带参的数据库语句
   * @param params 参数列表
   * @return
   * @throws Exception
   * sql="SELECT * FROM ADMIN where id=? AND　USER_NAME＝？"
   */
  protected List<Map> query(String sql, Object[] params)
          throws Exception {
      Connection conn = null;//数据库连接对象
      PreparedStatement ps = null;//数据库语句发送对象
      ResultSet rs = null;//查询得到的数据集对象
      List<Map> list = new ArrayList<Map>();//存放整个结果集
      /*try {
          conn = DBUtil.getConnection();//建立数据库连接
          ps = conn.prepareStatement(sql);//发送数据库语句
          if (params != null) {
              for (int i = 0; i < params.length; i++) {//如果有参数，则设置参数进语句发送对象中
                  ps.setObject(i + 1, params[i]);
              }
          }
          rs = ps.executeQuery();//执行查询动作
          ResultSetMetaData resultSetMetaData = rs.getMetaData();//获得表的所有元数据
          int columns = resultSetMetaData.getColumnCount();//获得表的列数
          while (rs.next()) {
              Map m = new HashMap();//一行的数据存到一个新的map集合
              for (int i = 0; i < columns; i++) {//通过遍历列数分别获得每一列数据类型
                  Object obj = null;//存本列的值
                  int type = resultSetMetaData.getColumnType(i + 1);//获得每一列数据类型
                  int scale = resultSetMetaData.getScale(i + 1);//获得每一列数据类型的精度
                  String columnName = resultSetMetaData.getColumnName(i + 1);//通过下标获得每一列名称
                  System.out.println("columnName:"+columnName+"  type:"+type+" scale:"+scale);
                  switch (type) {
                      case -1:
                          obj = rs.getObject(columnName);//以Object类型为结果获得本行此列的数据
                          break;
                      case 1:
                          obj = rs.getCharacterStream(columnName);//以Character类型为结果获得本行此列的数据
                          break;
                      case -5:
                          obj = Long.valueOf(rs.getLong(columnName));//以Long类型为结果获得本行此列的数据
                          break;
                      case 2://此类型是带有小数点的，需要分别对待处理
                          switch (scale) {
                              case 0:
                                  obj = Integer.valueOf(rs.getInt(columnName));//以Integer类型为结果获得本行此列的数据
                                  break;
                              case 2:
                                  obj = Double.valueOf(rs.getDouble(columnName));//以Double类型为结果获得本行此列的数据
                                  break;
                              case -127:
                                  obj = Float.valueOf(rs.getFloat(columnName));//以Float类型为结果获得本行此列的数据
                                  break;
                              default:
                                  obj = Integer.valueOf(rs.getInt(columnName));//以上都不符合默认以Integer类型为结果获得本行此列的数据
                          }
                          break;
                      case 12:
                          obj = rs.getString(columnName);//以String类型为结果获得本行此列的数据
                          break;
                      case 91:
                          obj = rs.getDate(columnName);//以Date类型为结果获得本行此列的数据
                          break;
                      case 93:
                          obj = rs.getTimestamp(columnName);//以Timestamp类型为结果获得本行此列的数据
                          break;
                      case 2004:
                          obj = rs.getBlob(columnName);//以Blob类型为结果获得本行此列的数据
                          break;
                      default:
                          obj = rs.getString(columnName);//以上都不符合默认以String类型为结果获得本行此列的数据
                  }
                  m.put(columnName.toUpperCase(), obj);//通过列名转成大写后作map的key,然后存这列的值obj
              }
              list.add(m);//把此行的数据存入list集合中
          }
      } catch (Exception e) {
          e.printStackTrace();
          throw new Exception(e.getMessage());
      } finally {
          DBUtil.close(rs);
          DBUtil.close(ps);
      }*/
      return list;//返回已经装载了所有行记录的集合
  }
  
	/**
	 * 数据操作日志
	 * @param o 操作的对象
	 * @param tableName 涉及的表名
	 * @param operateType 执行的动作类型
	 */
	public void dbLog(Object o,String tableName,String operateType){
		if("修改".equals(operateType)){
			System.out.println("修改了表："+tableName);
		}else if("新增".equals(operateType)){
			System.out.println("新增了表："+tableName);
		}else if("删除".equals(operateType)){
			System.out.println("查询了表："+tableName);
		}else if("查询".equals(operateType)){
			System.out.println("修改了表："+tableName);
		}
		System.out.println("数据信息："+o);
	}
	
	/**
	 * 
	 * 数据操作日志
	 *
	 * @param o 操作的对象
	 * @param tableName 涉及的表名
	 * @param operateType 执行的动作类型
	 */
	public void dugLog(Object o,String tableName,String operateType){
		if("修改".equals(operateType)){
			System.out.println("修改了表："+tableName);
		}else if("新增".equals(operateType)){
			System.out.println("新增了表："+tableName);
		}else if("删除".equals(operateType)){
			System.out.println("查询了表："+tableName);
		}else if("查询".equals(operateType)){
			System.out.println("修改了表："+tableName);
		}
		System.out.println("数据信息："+o);
	}
	
}
